﻿#include "market_clearing.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <map>  
#include <new>
#include <stdexcept>  // 用于异常处理

using namespace std;

// 全局存储申报数据（单线程场景安全）
PlantBid_C* plants = NULL;
int plantCount = 0;
UserBid_C* users = NULL;
int userCount = 0;

// 初始化：清空历史数据，防止内存泄漏
void initMarket() {
    // 释放发电侧旧内存（深拷贝数组需逐个释放）
    for (int i = 0; i < plantCount; i++) {
        delete[] plants[i].P;
        delete[] plants[i].C;
    }
    delete[] plants;
    plants = NULL;
    plantCount = 0;

    // 释放用户侧旧内存
    for (int i = 0; i < userCount; i++) {
        delete[] users[i].P;
        delete[] users[i].C;
    }
    delete[] users;
    users = NULL;
    userCount = 0;

    std::cout << "initMarket: 已清空所有申报数据内存" << std::endl;
}

void submitPlantBid(const PlantBid_C* bid) {
    if (bid == nullptr) {
        std::cerr << "submitPlantBid error: 传入的 bid 是空指针" << std::endl;
        return;
    }
    if (bid->segmentCount <= 0 || bid->P == nullptr || bid->C == nullptr) {
        std::cerr << "submitPlantBid error: 报价段数无效或数组指针为空" << std::endl;
        return;
    }

    // 1. 扩容发电侧数组
    PlantBid_C* newPlants = new PlantBid_C[plantCount + 1];
    // 2. 拷贝原有数据
    for (int i = 0; i < plantCount; i++) {
        newPlants[i] = plants[i];
    }
    // 3. 释放原数组内存
    delete[] plants;
    plants = newPlants;

    // 4. 深拷贝当前 bid 数据（与 Python 侧提交的结构完全匹配）
    int newIdx = plantCount;
    plants[newIdx].plantName = bid->plantName;    // Python 侧已 encode 为 UTF-8 字符串
    plants[newIdx].unitNo = bid->unitNo;
    plants[newIdx].segmentCount = bid->segmentCount;

    // 深拷贝出力数组 P（与 Python 侧 [50,80] 等列表对应）
    plants[newIdx].P = new double[bid->segmentCount];
    for (int i = 0; i < bid->segmentCount; i++) {
        plants[newIdx].P[i] = bid->P[i];
    }
    // 深拷贝报价数组 C（与 Python 侧 [300,350] 等列表对应）
    plants[newIdx].C = new double[bid->segmentCount];
    for (int i = 0; i < bid->segmentCount; i++) {
        plants[newIdx].C[i] = bid->C[i];
    }

    plantCount++;
    std::cout << "submitPlantBid: 成功提交发电侧数据（" << bid->plantName << "），当前总数=" << plantCount << std::endl;
}
// 提交用户侧申报（与发电侧逻辑对称，适配 Python 数据）
void submitUserBid(const UserBid_C* bid) {
    if (bid == nullptr) {  
        std::cerr << "submitUserBid error: 传入的 bid 是空指针" << std::endl;
        return;
    }
    if (bid->segmentCount <= 0 || bid->P == nullptr || bid->C == nullptr) {  
        std::cerr << "submitUserBid error: 报价段数无效或数组指针为空" << std::endl;
        return;
    }

    // 1. 扩容用户侧数组
    UserBid_C* newUsers = new UserBid_C[userCount + 1];
    // 2. 拷贝原有数据
    for (int i = 0; i < userCount; i++) {
        newUsers[i] = users[i];
    }
    // 3. 释放原数组内存
    delete[] users;
    users = newUsers;

    // 4. 深拷贝当前 bid 数据（与 Python 侧提交的结构完全匹配）
    int newIdx = userCount;
    users[newIdx].userName = bid->userName;    // Python 侧已 encode 为 UTF-8 字符串
    users[newIdx].userNo = bid->userNo;        
    users[newIdx].segmentCount = bid->segmentCount;

    // 深拷贝负荷数组 P（与 Python 侧 [40,60] 等列表对应）
    users[newIdx].P = new double[bid->segmentCount];
    for (int i = 0; i < bid->segmentCount; i++) {
        users[newIdx].P[i] = bid->P[i];
    }
    // 深拷贝报价数组 C（与 Python 侧 [500,450] 等列表对应）
    users[newIdx].C = new double[bid->segmentCount];
    for (int i = 0; i < bid->segmentCount; i++) {
        users[newIdx].C[i] = bid->C[i];
    }

    userCount++;
    std::cout << "submitUserBid: 成功提交用户侧数据（" << bid->userName << "），当前总数=" << userCount << std::endl;
}
// 提交用户侧申报（与发电侧逻辑对称，适配 Python 数据）
void submitUserBid(const UserBid_C* bid) {
    if (bid == nullptr) {
        std::cerr << "submitUserBid error: 传入的 bid 是空指针" << std::endl;
        return;
    }
    if (bid->segmentCount <= 0 || bid->P == nullptr || bid->C == nullptr) {
        std::cerr << "submitUserBid error: 报价段数无效或数组指针为空" << std::endl;
        return;
    }

    // 1. 扩容用户侧数组
    UserBid_C* newUsers = new UserBid_C[userCount + 1];
    // 2. 拷贝原有数据
    for (int i = 0; i < userCount; i++) {
        newUsers[i] = users[i];
    }
    // 3. 释放原数组内存
    delete[] users;
    users = newUsers;

    // 4. 深拷贝当前 bid 数据（与 Python 侧提交的结构完全匹配）
    int newIdx = userCount;
    users[newIdx].userName = bid->userName;    // Python 侧已 encode 为 UTF-8 字符串
    users[newIdx].userNo = bid->userNo;
    users[newIdx].segmentCount = bid->segmentCount;

    // 深拷贝负荷数组 P（与 Python 侧 [40,60] 等列表对应）
    users[newIdx].P = new double[bid->segmentCount];
    for (int i = 0; i < bid->segmentCount; i++) {
        users[newIdx].P[i] = bid->P[i];
    }
    // 深拷贝报价数组 C（与 Python 侧 [500,450] 等列表对应）
    users[newIdx].C = new double[bid->segmentCount];
    for (int i = 0; i < bid->segmentCount; i++) {
        users[newIdx].C[i] = bid->C[i];
    }

    userCount++;
    std::cout << "submitUserBid: 成功提交用户侧数据（" << bid->userName << "），当前总数=" << userCount << std::endl;
}

// 出清核心：构建供需曲线并找交点（与 Python 侧 calculate_*_curve / find_clearing_point 逻辑完全对齐）
ClearingResult_C* clearMarket() {
    // 1. 校验申报数据（无数据返回错误码，Python 侧可识别）
    if (plantCount == 0 || userCount == 0 || plants == NULL || users == NULL) {
        std::cerr << "clearMarket error: 无有效发电侧或用户侧申报数据！" << std::endl;
        return (ClearingResult_C*)0x1;  // 错误码1：无数据
    }
    std::cout << "\nclearMarket: 开始出清，发电侧=" << plantCount << "个，用户侧=" << userCount << "个" << std::endl;

    // 2. 初始化出清结果（清空内存，避免野指针）
    ClearingResult_C* result = new ClearingResult_C();
    memset(result, 0, sizeof(ClearingResult_C));

    try {
        // 3. 分配结果数组内存（与 Python 侧表格展示字段对应）
        // 3.1 发电侧结果数组（存储电厂名称、出清电量、收入）
        result->plantResultCount = plantCount;
        result->plantNames = new const char* [plantCount];
        result->plantClearedP = new double[plantCount];
        result->plantIncome = new double[plantCount];
        if (!result->plantNames || !result->plantClearedP || !result->plantIncome) {
            throw std::bad_alloc();
        }

        // 3.2 用户侧结果数组（存储用户名、出清负荷、账单）
        result->userResultCount = userCount;
        result->userNames = new const char* [userCount];
        result->userClearedP = new double[userCount];
        result->userBill = new double[userCount];
        if (!result->userNames || !result->userClearedP || !result->userBill) {
            throw std::bad_alloc();
        }
        std::cout << "clearMarket: 结果数组内存分配完成" << std::endl;

        // 4. 【核心1】构建供应曲线（同价合并+升序，与 Python calculate_supply_curve 一致）
        vector<pair<double, double>> plant_curve;  // <累计电量, 报价>
        double total_plant = 0.0;
        map<double, double> plant_price_map;       // 同价合并：key=报价，value=总出力

        for (int i = 0; i < plantCount; i++) {
            result->plantNames[i] = plants[i].plantName;  // 关联电厂名称
            for (int j = 0; j < plants[i].segmentCount; j++) {
                double price = plants[i].C[j];
                double power = plants[i].P[j];

                // 过滤无效数据（与 Python 侧校验逻辑一致）
                if (price <= 0 || power <= 0) {
                    std::cerr << "警告：" << plants[i].plantName << "第" << j + 1 << "段数据无效（价格/出力≤0），已跳过" << std::endl;
                    continue;
                }
                plant_price_map[price] += power;  // 同价出力合并
            }
        }

        // 生成供应曲线（升序阶梯，与 Python 侧曲线结构完全相同）
        for (auto& [price, total_power] : plant_price_map) {
            total_plant += total_power;
            plant_curve.emplace_back(total_plant, price);
        }
        if (plant_curve.empty()) {
            throw std::runtime_error("发电侧无有效数据，无法构建供应曲线");
        }

        // 5. 【核心2】构建需求曲线（同价合并+降序，与 Python calculate_demand_curve 一致）
        vector<pair<double, double>> user_curve;   // <累计电量, 报价>
        double total_user = 0.0;
        map<double, double, greater<double>> user_price_map;  // 同价合并：key=报价（降序），value=总负荷

        for (int i = 0; i < userCount; i++) {
            result->userNames[i] = users[i].userName;  // 关联用户名
            for (int j = 0; j < users[i].segmentCount; j++) {
                double price = users[i].C[j];
                double power = users[i].P[j];

                // 过滤无效数据（与 Python 侧校验逻辑一致）
                if (price <= 0 || power <= 0) {
                    std::cerr << "警告：" << users[i].userName << "第" << j + 1 << "段数据无效（价格/负荷≤0），已跳过" << std::endl;
                    continue;
                }
                user_price_map[price] += power;  // 同价负荷合并
            }
        }

        // 生成需求曲线（降序阶梯，与 Python 侧曲线结构完全相同）
        for (auto& [price, total_power] : user_price_map) {
            total_user += total_power;
            user_curve.emplace_back(total_user, price);
        }
        if (user_curve.empty()) {
            throw std::runtime_error("用户侧无有效数据，无法构建需求曲线");
        }

        // 6. 【核心3】找供需交点（区间重叠逻辑，与 Python find_clearing_point 完全一致）
        double clearing_price = 0.0, cleared_p = 0.0;
        int p_idx = 0, u_idx = 0;
        double prev_plant_q = 0.0, prev_user_q = 0.0;  // 上一段累计电量（区间起点）

        while (p_idx < plant_curve.size() && u_idx < user_curve.size()) {
            // 当前供应段：[prev_plant_q, curr_plant_q]，报价 curr_plant_price
            double curr_plant_q = plant_curve[p_idx].first;
            double curr_plant_price = plant_curve[p_idx].second;
            // 当前需求段：[prev_user_q, curr_user_q]，报价 curr_user_price
            double curr_user_q = user_curve[u_idx].first;
            double curr_user_price = user_curve[u_idx].second;

            // 区间重叠判断（核心逻辑，与 Python 完全对齐）
            if (curr_plant_q > prev_user_q && curr_user_q > prev_plant_q) {
                cleared_p = min(curr_plant_q, curr_user_q) - max(prev_plant_q, prev_user_q);
                clearing_price = curr_user_price;  // 出清价取需求侧报价
                break;
            }

            // 推进累计电量较小的区间（继续查找）
            if (curr_plant_q < curr_user_q) {
                prev_plant_q = curr_plant_q;
                p_idx++;
            }
            else {
                prev_user_q = curr_user_q;
                u_idx++;
            }
        }

        // 极端情况：无重叠区间（优化逻辑，避免 0 电价）
        if (p_idx >= plant_curve.size() || u_idx >= user_curve.size()) {
            cleared_p = min(total_plant, total_user);
            // 取边界价格（供应不足取供应最高报价，需求不足取需求最低报价）
            clearing_price = (total_plant <= total_user) ?
                plant_curve.back().second : user_curve.back().second;
            std::cout << "警告：供需无重叠，按边界价格出清（电价=" << clearing_price << "）" << std::endl;
        }

        // 7. 填充基础出清结果（与 Python 侧绘图用出清点字段对应）
        result->clearingPrice = clearing_price;
        result->totalClearedP = cleared_p;

        // 8. 分配电厂/用户出清量（按总出力/负荷占比，与业务逻辑适配）
        // 8.1 发电侧分配
        for (int i = 0; i < plantCount; i++) {
            double plant_total_p = 0.0;
            for (int j = 0; j < plants[i].segmentCount; j++) {
                plant_total_p += plants[i].P[j];
            }
            // 按占比分配（与 Python 侧表格展示逻辑一致）
            result->plantClearedP[i] = (cleared_p > 0 && total_plant > 0) ?
                plant_total_p * (cleared_p / total_plant) : 0.0;
            result->plantIncome[i] = result->plantClearedP[i] * clearing_price;
        }

        // 8.2 用户侧分配
        for (int i = 0; i < userCount; i++) {
            double user_total_p = 0.0;
            for (int j = 0; j < users[i].segmentCount; j++) {
                user_total_p += users[i].P[j];
            }
            // 按占比分配（与 Python 侧表格展示逻辑一致）
            result->userClearedP[i] = (cleared_p > 0 && total_user > 0) ?
                user_total_p * (cleared_p / total_user) : 0.0;
            result->userBill[i] = result->userClearedP[i] * clearing_price;
        }

        // 9. 打印曲线日志（方便与 Python 侧日志对比，确认数据一致）
        std::cout << "\n=== 供应曲线（累计电量MW, 报价元/MWh）===" << std::endl;
        for (auto& seg : plant_curve) {
            std::cout << "(" << seg.first << ", " << seg.second << ")" << std::endl;
        }
        std::cout << "=== 需求曲线（累计电量MW, 报价元/MWh）===" << std::endl;
        for (auto& seg : user_curve) {
            std::cout << "(" << seg.first << ", " << seg.second << ")" << std::endl;
        }
        std::cout << "\n出清结果：电量=" << cleared_p << "MW，电价=" << clearing_price << "元/MWh" << std::endl;

        return result;

    }
    catch (const bad_alloc& e) {
        // 内存分配失败：释放已分配内存
        std::cerr << "clearMarket error: 内存分配失败 - " << e.what() << std::endl;
        freeClearingResult(result);
        return (ClearingResult_C*)0x2;  // 错误码2：内存错误
    }
    catch (const runtime_error& e) {
        // 业务逻辑错误：释放内存
        std::cerr << "clearMarket error: " << e.what() << std::endl;
        freeClearingResult(result);
        return (ClearingResult_C*)0x3;  // 错误码3：业务错误
    }
    catch (...) {
        // 未知错误：释放内存
        std::cerr << "clearMarket error: 未知错误" << std::endl;
        freeClearingResult(result);
        return (ClearingResult_C*)0x4;  // 错误码4：未知错误
    }
}

// 释放出清结果内存（与 Python 侧调用逻辑适配，避免内存泄漏）
void freeClearingResult(ClearingResult_C* result) {
    if (result == nullptr) {
        return;
    }

    // 释放发电侧结果数组（与 clearMarket 中分配顺序对应）
    delete[] result->plantNames;
    delete[] result->plantClearedP;
    delete[] result->plantIncome;

    // 释放用户侧结果数组
    delete[] result->userNames;
    delete[] result->userClearedP;
    delete[] result->userBill;

    // 释放结果结构体本身
    delete result;
    std::cout << "freeClearingResult: 出清结果内存已全部释放" << std::endl;
}

// 声明动态库导出函数（确保 Python ctypes 能正确识别）
extern "C" {
    void initMarket();
    void submitPlantBid(const PlantBid_C* bid);
    void submitUserBid(const UserBid_C* bid);
    ClearingResult_C* clearMarket();
    void freeClearingResult(ClearingResult_C* result);
}